import 'dart:core';

import 'package:charset_converter/charset_converter.dart';
import 'package:html/dom.dart';
import 'package:html/parser.dart' show parse;
import 'package:http/http.dart' as http;

Future<Map<String, String>> readStringFromUrl(String url1) async {
  Map<String, String> ret;

  // List<String> charsets = await CharsetConverter.availableCharsets();
  // for(var e in charsets){
  //   print('fhz: $e');
  // }

  var client = http.Client();
  Uri uri1 = Uri.parse(url1);

  var response = await client.get(uri1);
  client.close();
  var c1 = getCharset(response.headers['content-type'].toString());
  bool isAvailable = await CharsetConverter.checkAvailability(c1);
  //print('fhz: $c1 :$isAvailable');
  //await CharsetConverter.checkAvailability(c1);
  var res = response.body;
  if (isAvailable) {
    res = await CharsetConverter.decode(c1, response.bodyBytes);
  }

  //print('fhz: ' + url1 + '=>' + response.headers['content-type'].toString());
  var contentType = response.headers['content-type'].toString();
  if (contentType.length > 10) {
    contentType = contentType.substring(0, 10);
  }
  ret = {
    'body': res,
    'type': contentType,
  };
  return ret;
}

Map<String, String> myParseUrl(String url1) {
  var ret = {'base': '', 'path': '', 'name': ''};
  if (url1.length < 7) {
    return ret;
  }
  if (url1.toLowerCase().startsWith(RegExp(r'https?://')) == false) {
    //print('fhz: $url1 is not a URL');
    return ret;
  }
  // like: http://www.host.com
  var breaks = '/'.allMatches(url1, 8).toList();
  if (breaks.isEmpty) {
    ret['base'] = url1;
    ret['path'] = '/';
    //print('fhz: $ret');
    return ret;
  }

  if (url1.endsWith('/')) {
    // like: http://www.host.com/path1/

    ret['path'] = url1.substring(breaks[0].end - 1);
    //print('fhz: $ret');
    return ret;
  } else {
    // like: http://www.host.com/path/name.html
    ret['base'] = url1.substring(0, breaks[0].end - 1);
    int end = breaks.length - 1;
    int break2 = breaks[end].end;
    ret['path'] = url1.substring(breaks[0].end, break2);
    ret['name'] = url1.substring(break2);
    //print('fhz: $ret');
    return ret;
  }
}

String getRealUrl(String href, Map<String, String> base1) {
  if (href.toLowerCase().startsWith(RegExp(r'https?://'))) {
    // 本来就是url
    return href;
  }
  if (href.startsWith('/')) {
    return '${base1['base']}$href';
  } else {
    return '${base1['base']}${base1['path']}$href';
  }
}

List<List<String>> getLinksFromHtml(
  String html1, [
  String baseUrl = '',
]) {
  final base1 = myParseUrl(baseUrl);
  var ret = List<List<String>>.empty(growable: true);
  late Document document;
  try {
    document = parse(html1.toLowerCase());
  } catch (e) {
    return ret;
  }
  var links = document.getElementsByTagName('a');
  if (links.isEmpty) {
    return ret;
  }
  for (var e in links) {
    var href = e.attributes['href'];
    var name = e.text;
    ret.add([name, getRealUrl(href!, base1)]);
  }
  return ret;
}

String getCharset(String contentType) {
  if (contentType.contains('charset=') == false) {
    return 'utf-8';
  }
  var list1 = contentType.split('charset=');
  return list1[list1.length - 1].toLowerCase();
}

String getTextFromHtml(String html1, [String encoding = 'utf-8']) {
  //print('fhz: getTextFromHtml $encoding');
  late Document document;
  try {
    document = parse(html1.toLowerCase(), encoding: encoding);
  } catch (e) {
    return html1;
  }

  var labels = ['script','a','ul','input'];
  for(var name in labels) {
    var elements = document.getElementsByTagName(name);
    for(var e in elements) {
      e.remove();
    }
  }
  // var scripts = document.getElementsByTagName('script');
  // for (var e in scripts) {
  //   e.remove();
  // }
  // var hrefs = document.getElementsByTagName('a');
  // for(var e in hrefs) {
  //   e.remove();
  // }
  return document.body!.text;
  // var h1 = document.getElementsByTagName('h1');
  // var vals = List<String>.empty(growable: true);
  // for (var e in h1) {
  //   vals.add(e.text);
  // }
  // var h2 = document.getElementsByTagName('h2');
  // for (var e in h2) {
  //   vals.add(e.text);
  // }
  // var pList = document.getElementsByTagName('p');
  // for (var e in pList) {
  //   vals.add(e.text);
  // }
  // return vals.join('\n');
}

List<String> splitText(String text1) {
  var list1 = List<String>.empty(growable: true);
  var regexp1 = RegExp(r'[。，？！”.!?,、\n]+');
  var res = regexp1.allMatches(text1);
  var start = 0;
  for (var m in res) {
    //print('${m.start}->${m.end}:${text1.substring(start, m.end)}');
    list1.add(text1.substring(start, m.end).trim());
    start = m.end;
  }
  return list1;
}

List<String> mergeTextLimited(List<String> list1) {
  var res = List<String>.empty(growable: true);
  const int maxLength = 60;
  int start = 0;
  for (int i = 0; i < list1.length; i++) {
    int len = 0;
    for (int i2 = start; i2 <= i; i2++) {
      len += list1[i2].length;
    }
    if (len > maxLength) {
      int pos = i - 1;
      if (pos < start) {
        pos = start;
      }
      res.add(list1.sublist(start, pos + 1).join(' '));
      start = pos + 1;
    }
  }
  if (start < list1.length) {
    res.add(list1.sublist(start, list1.length).join('\n'));
  }
  // for (int i = 0; i < res.length; i++) {
  //   print('$i>${res[i]}(${res[i].length})');
  // }
  return res;
}
